/**
 * 
 */
package ua.lviv.franko.solvers.oneDimention;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import ua.lviv.franko.FEMShapeFunction1D.FEMShapeFunction1D1;
import ua.lviv.franko.integration.GaussQuadrature;
import ua.lviv.franko.integration.IFunction1D;
import ua.lviv.franko.integration.Quadrature;
import ua.lviv.franko.mlsFunctions.oneDimension.ICalculate;
import ua.lviv.franko.mlsFunctions.oneDimension.weightFunctions.IWeightFunction;
import ua.lviv.franko.solvers.ElementMatrix;
import ua.lviv.franko.solvers.IElement1D;
import ua.lviv.franko.visualisation.NewOkCancelDialog;

/**
 * @author marko
 * 
 */
public class EnrichedLinearElementWithFEM implements IElement1D {
	public int						QuadraturePointsNumber	= 20;

	// problem data
	protected EquationParameters	eParams;
	// element number starting from 0
	protected int					elNumber;
	// element information
	protected double				left;
	protected double				right;
	// results
	protected ElementMatrix			data;
	// EFG variables;
	protected int					Degree;
	protected int					numberOfFEMNodes;
	protected IWeightFunction		weight;
	protected double				rho;

	private List<ICalculate>		baseFunctions;
	private List<Integer>			pos;

	public EnrichedLinearElementWithFEM(EquationParameters eParams, double left, double right, int firstNumber, int numberOfFEMNodes) {
		this.elNumber = firstNumber;
		this.eParams = eParams;
		this.left = left;
		this.right = right;
		this.numberOfFEMNodes = numberOfFEMNodes;

		double h = (right - left) / numberOfFEMNodes;
		baseFunctions = new ArrayList<ICalculate>();
		for (int i = 0; i <= numberOfFEMNodes; i++) {
			baseFunctions.add(new FEMShapeFunction1D1(left + h * i, h));
		}
		pos = new ArrayList<Integer>(baseFunctions.size());
		for (int i = 0; i < baseFunctions.size(); i++) {
			pos.add(this.elNumber + i);
		}
	}

	@Override
	public double calculate(double x, double[] vals) {
		int pos = elNumber;
		double val = 0.0;
		for (Iterator<ICalculate> iterator = this.baseFunctions.iterator(); iterator.hasNext();) {
			ICalculate func = iterator.next();
			val += func.calculate(x) * vals[pos];
			pos++;
		}
		return val;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see solvers.IElement#generateAll()
	 */
	@Override
	public void generateAll() {
		Quadrature gau = new GaussQuadrature(QuadraturePointsNumber);
		// final EquationParameters finalEP = this.eParams;

		// generating values
		data = new ElementMatrix(pos);
		for (int i = 0; i < data.vector.length; i++) {
			final ICalculate phi1 = baseFunctions.get(i);
			double[] bounds = phi1.getBounds();
			bounds[0] = Math.max(left, bounds[0]);
			bounds[1] = Math.min(right, bounds[1]);
			for (int j = 0; j < data.vector.length; j++) {
				final ICalculate phi2 = baseFunctions.get(j);
				double value = gau.integrate(bounds[0], bounds[1], new IFunction1D() {

					@Override
					public double calculate(double x) {
						double[] r1 = phi2.calculateAll(x);
						double[] r2 = phi1.calculateAll(x);
						return eParams.p.calculate(x) * r1[1] * r2[1] + eParams.w.calculate(x) * r1[1] * r2[0] + eParams.q.calculate(x) * r1[0] * r2[0];
					}

					@Override
					public double calculateDerivaty(double x) {

						return 0;
					}
				});
				data.matrix[i][j] = (value);
			}
			data.vector[i] = gau.integrate(bounds[0], bounds[1], new IFunction1D() {

				@Override
				public double calculate(double x) {
					double r1 = phi1.calculate(x);
					return eParams.f.calculate(x) * r1;
				}

				@Override
				public double calculateDerivaty(double x) {
					return 0.0;
				}
			});
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see solvers.IElement#generateFe()
	 */
	@Override
	public double[] generateFe() {

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see solvers.IElement#generatePe()
	 */
	@Override
	public double[][] generatePe() {

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see solvers.IElement#generateQe()
	 */
	@Override
	public double[][] generateQe() {

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see solvers.IElement#generateWe()
	 */
	@Override
	public double[][] generateWe() {

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see solvers.IElement#getAll()
	 */
	@Override
	public ElementMatrix getAll() {
		return data;
	}

	@Override
	public int lastNumber() {
		return this.elNumber + baseFunctions.size() - 1;
	}

	public static void main(String[] args) {

		// // display functions ...
		XYSeriesCollection col = new XYSeriesCollection();
		// int position = 0;
		double left = 0.0;
		double right = 1.0;

		EnrichedLinearElementWithFEM elem = new EnrichedLinearElementWithFEM(new EquationParameters(), left, right, 0, 10);
		for (Iterator<ICalculate> iterator = elem.baseFunctions.iterator(); iterator.hasNext();) {

			ICalculate jmf1 = iterator.next();
			XYSeries s = new XYSeries("1", true, true);
			double xxx = left;
			while (xxx <= right + 0.0001) {
				double tmp1 = jmf1.calculateAll(xxx)[0];
				s.add(xxx, tmp1);
				xxx += 0.0002;
			}
			// position++;
			col.addSeries(s);
		}

		NewOkCancelDialog d = new NewOkCancelDialog(null, false, col);
		d.setLocationRelativeTo(null);
		d.setVisible(true);

	}

}
